package mn.asri.teaproc.server;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import mn.asri.teaproc.client.BaseModel;
import mn.asri.teaproc.client.PocAnswer;
import mn.asri.teaproc.client.PocPayload;
import mn.asri.teaproc.client.PocQuestion;
import mn.asri.teaproc.client.PocReferencedObject;
import mn.asri.teaproc.client.PocRpcService;

/**
 * the server-side RPC for this POC.  Two main methods:
 * <code>receiveInitialQuestion()</code> and <code>sendAnswerAndReceiveQuestion()</code>
 * are used here.  This code used an internal array to store sample questions.
 */
public class PocRpcServiceImpl extends RemoteServiceServlet
	implements PocRpcService {

	private Properties prop;

	public void init(ServletConfig config) throws ServletException {
		super.init(config);

		String propFile = config.getInitParameter("questionFile");
		// todo: added here because GWT in hosted mode does not read the web.xml file (in web/WEB-INF).
		if (propFile == null) {
			propFile = "/mn/asri/teaproc/server/questions.properties";
		}

		try {
			prop = new Properties();
			InputStream in = this.getClass().getResourceAsStream(propFile);
			prop.load(in);
		} catch (IOException e) {
			throw new ServletException(e);
		}
	}

	/** called initially by the client to get the first question. */
	public PocPayload receiveInitialQuestion() {
		System.out.println("getting initial question");
		PocQuestion q = getFirstQuestion();
		System.out.println("q.getIndex() = " + q.getIndex());
		System.out.println("q.getText() = " + q.getText());
		return ServerModelUtil.toPayload(q.deserialize());
	}

	/** called subsequently by the client after having the initial question. */
	public PocPayload sendAnswerAndReceiveQuestion(PocPayload wrappedAnswer) {
		PocAnswer answer = (PocAnswer) unwrap(wrappedAnswer, PocAnswer.class);
		System.out.println("received answer...");
		System.out.println(".getTestId() = " + answer.getTestId());
		System.out.println(".getIndex() = " + answer.getIndex());
		System.out.println(".getAnswerIndex() = " + answer.getAnswerIndex());
		System.out.println(".getCurrentTime() = " + answer.getCurrentTime());
		System.out.println("getting next question...");
		BaseModel q = getQuestion(answer.getNextQuestionIndex());
		return ServerModelUtil.toPayload(q.deserialize());
	}

	/** "deserialize" the <code>payload</code> to the actual data model. */
	private static BaseModel unwrap(PocPayload payload, Class clazz) {
		BaseModel real = null;
		try {
			real = (BaseModel) Class.forName(clazz.getName()).newInstance();
			ServerModelUtil.toModel(payload, real);
			//real.serial(payload);
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return real;
	}

	private PocQuestion getFirstQuestion() {
		PocQuestion q = new PocQuestion();
		q.setIndex(1);
		q.setServerTicks(System.currentTimeMillis());
		q.setText(prop.getProperty("q1"));
		q.setType(PocQuestion.TYPE_MCQ);

		// added this dummy object to show that the crypto is working with nested object
		PocReferencedObject pro = new PocReferencedObject();
		pro.setData("POCREFERENCEDOBJECT");
		q.setReferencedObject(pro);

		q.setResponses(new String[]{"1000km",
		                            "2000km",
		                            "3000km",
		                            "none of the above"});
		return q;
	}

	private PocQuestion getQuestion(int questionIndex) {
		PocQuestion q = new PocQuestion();
		q.setIndex(questionIndex);
		q.setServerTicks(System.currentTimeMillis());
		String questionText = prop.getProperty("q" + (questionIndex + 1));
		if (questionText == null) {
			q.setText(prop.getProperty("q1"));
		} else {
			q.setText(questionText);
		}

		q.setType(PocQuestion.TYPE_MCQ);

		// added this dummy object to show that the crypto is working with nested object
		PocReferencedObject pro = new PocReferencedObject();
		pro.setData("POCREFERENCEDOBJECT " + questionIndex);
		q.setReferencedObject(pro);

		// dummy
		q.setResponses(new String[]{"yellow",
		                            "red",
		                            "blue",
		                            "none of the above"});
		return q;
	}

}